Skip to content

perf(Core): Reduce zero length array allocations#851

Open
Numpsy wants to merge 1 commit into
fsprojects:masterfrom
Numpsy:reduce_empty_arrays
Open

perf(Core): Reduce zero length array allocations#851
Numpsy wants to merge 1 commit into
fsprojects:masterfrom
Numpsy:reduce_empty_arrays

Conversation

@Numpsy

@Numpsy Numpsy commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

…r to reduce the number of allocated zero length arrays.

As it stands, running the rules allocates a massive number of zero length arrays, which has quite a large effect on the amount of memory allocated. Many of these are from FSharp.Core functions which always create a new array, but which can be avoided with small local wrappers.


Just trying to get back to looking at some perf tests I started some time back, and found this one.

Running the Visual Studio memory profiler on the functions in the benchmarks project shows the allocations of massive numbers of zero length arrays (over 4 million in total). e.g.

image image

If I run the benchmarks project with memory diagnosis enabled, I get this with the current code

| Method         | Mean     | Error   | StdDev  | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|--------:|--------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 878.0 ms | 4.17 ms | 3.70 ms | 25000.0000 | 8000.0000 | 1000.0000 | 396.83 MB |

Down to this with this change

| Method         | Mean     | Error    | StdDev   | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|---------:|---------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 865.0 ms | 12.17 ms | 10.79 ms | 20000.0000 | 7000.0000 | 1000.0000 | 321.69 MB |

If I enable all of the extra checks that are enabled in the 'run self checks' leg of the CI then the differences are even larger.
Before

| Method         | Mean    | Error    | StdDev   | Gen0       | Gen1       | Gen2      | Allocated |
|--------------- |--------:|---------:|---------:|-----------:|-----------:|----------:|----------:|
| LintParsedFile | 1.402 s | 0.0164 s | 0.0146 s | 43000.0000 | 14000.0000 | 3000.0000 | 726.16 MB |

After

| Method         | Mean    | Error    | StdDev   | Gen0       | Gen1       | Gen2      | Allocated |
|--------------- |--------:|---------:|---------:|-----------:|-----------:|----------:|----------:|
| LintParsedFile | 1.380 s | 0.0141 s | 0.0125 s | 36000.0000 | 11000.0000 | 3000.0000 | 622.94 MB |

These allocations are caused by FSHarp.Core liking to always create new arrays in various Array functions, but to me it looks like it's a big enough gain to special case it locally?...

Note: There are other places that could maybe be changed as well, and a similar situation with Array.collect, but I left it just doing one thing to get comments.

@Numpsy Numpsy changed the title Change the 'run ruie' functions to special case empty arrays, in orde… Change the 'run rule' functions to special case empty arrays, in orde… Apr 26, 2026
@Numpsy Numpsy force-pushed the reduce_empty_arrays branch from 749e33e to 093f1c2 Compare April 26, 2026 11:16
@knocte knocte force-pushed the reduce_empty_arrays branch from 093f1c2 to 0ca7b9e Compare June 5, 2026 07:31
@knocte

knocte commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

@Numpsy LGTM, can you remove DRAFT status?

Also I see a typo in commit msg "ruie" -> "rule" and now that you're going to fix it, please reduce the title (1st line) to max 50 chars, and make commit msg body same as PR description. Thanks

@Numpsy Numpsy force-pushed the reduce_empty_arrays branch from 0ca7b9e to df5a7eb Compare June 21, 2026 11:07
@Numpsy Numpsy changed the title Change the 'run rule' functions to special case empty arrays, in orde… Reduce zero length array allocations Jun 21, 2026
@Numpsy

Numpsy commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

and make commit msg body same as PR description.

Do you want the benchmark numbers in the commit message, or just the description of the change?

@Numpsy Numpsy marked this pull request as ready for review June 21, 2026 11:32
@Numpsy Numpsy force-pushed the reduce_empty_arrays branch from df5a7eb to d93c0cc Compare June 21, 2026 11:49
@knocte

knocte commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

Do you want the benchmark numbers in the commit message

Why leave any info outside the commit msg? If you do that, it will be lost when/if this repo moves to a different git hosting platform.

When you add those, can you also:

  • Wrap commit msg body at 64chars per line max.
  • Add "perf(Core): " before commit msg title.

With that, I'll merge.

@Numpsy Numpsy changed the title Reduce zero length array allocations perf(Core): Reduce zero length array allocations Jun 21, 2026
Running the Visual Studio memory analyzer against the
benchmarks project reveals that the current code is allocating
a massive number of zero length arrays (over 3 million in that
one benchmark).

Many of these are from the Array functions in FSharp.Core
always allocating a new empty array for an empty input.
There are enough of these that avoiding some calls to
Array.map with zero length inputs give a large reduction in
memory allocations.

Benchmarks with the current code:
| Method         | Mean     | Error   | StdDev  | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|--------:|--------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 878.0 ms | 4.17 ms | 3.70 ms | 25000.0000 | 8000.0000 | 1000.0000 | 396.83 MB |

Benchmarks with this change:
| Method         | Mean     | Error    | StdDev   | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|---------:|---------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 865.0 ms | 12.17 ms | 10.79 ms | 20000.0000 | 7000.0000 | 1000.0000 | 321.69 MB |
@Numpsy Numpsy force-pushed the reduce_empty_arrays branch from d93c0cc to 24bd073 Compare June 21, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants